package com.gitee.apanlh.util.dataformat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.check.CheckImport;
import com.gitee.apanlh.util.check.CheckLibrary;
import com.gitee.apanlh.util.encode.StrEncodeUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * 	JSON工具类集合
 * 	<br>基于FastJson1
 * 	
 * 	@author Pan
 */
public class JsonUtils {
	
	static {
		CheckImport.library(CheckLibrary.FASTJSON);
	}
	
	private static final char JSON_START_TAG = '{';
	private static final char JSON_END_TAG = '}';
	private static final char JSON_ARRAY_START_TAG = '[';
	private static final char JSON_ARRAY_END_TAG = ']';
	
	/**
	 * 	默认构造函数
	 * 	@author Pan
	 */
	private JsonUtils() {
		//	不允许实例化
		super();
	}
	
	/**	
	 * 	获取解析的对象
	 * 	
	 * 	@author Pan
	 * 	@param 	json	json字符串
	 * 	@return	JSONObject
	 */
	public static JSONObject get(String json) {
		return JSON.parseObject(json);
	}
	
	/**	
	 * 	指定获取某一节点的JSON数据
	 * 
	 * 	@author Pan
	 * 	@param 	json	json字符串
	 * 	@param 	node	json节点
	 * 	@return	String
	 */
	public static String getNode(String json, String node) {
		return String.valueOf(JSON.parseObject(json).get(node));
	}
	
	/**
	 * 	Json字符串 转换javaBean
	 * 	<br>Json只可有单个对象
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  json 	json字符串
	 * 	@param  clazz 	类
	 * 	@return T
	 */
	public static <T> T toBean(String json, Class<T> clazz) {
		return JSON.parseObject(checkJson(json), clazz);
	}
	
	/**	
	 * 	自定义转换类型
	 * 	
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param 	json	json字符串
	 * 	@param 	type	转换类型
	 * 	@return	T
	 */
	public static <T> T toBean(String json, TypeReference<T> type) {
		return JSON.parseObject(checkJson(json), type);
	}
	
	/**
	 * 	Json字符串  转换List 集合
	 * 	<br>也可适用于{@code List<Map<String,T>>等}
	 * 	<br>必须是Json里有多个对象
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  json	 json字符串
	 * 	@param  clazz	 类
	 * 	@return List
	 */
	public static <T> List<T> toList(String json, Class<T> clazz) {
		return JSON.parseArray(checkJson(json), clazz);
	}
	
	/**
	 * 	byte的ListJson转换成List对象
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      		数据类型
	 * 	@param  jsonListByte 	必须存放的是jsonList对象
	 * 	@param  clazz 			类名
	 * 	@return	List			返回List对象
	 */
	public static <T> List<T> toList(byte[] jsonListByte, Class<T> clazz) {
		return JSON.parseArray(StrEncodeUtils.utf8EncodeToStr(jsonListByte), clazz);
	}
	
	/**
	 * 	json字符串解析为Map对象
	 * 
	 * 	@author Pan
	 * 	@param  json	json字符串
	 * 	@return Map
	 */
	public static Map<String, Object> toMap(String json) {
		return JSON.parseObject(checkJson(json)).getInnerMap();
	}

	/**
	 * 	json解析为Map对象
	 * 	<br>返回Map顺序与返回JSON顺序一致
	 * 	
	 * 	@author Pan
	 * 	@param  json	json字符串
	 * 	@return Map
	 */
	public static Map<String, Object> toMapOrder(String json) {
		return JSON.parseObject(checkJson(json), new TypeReference<LinkedHashMap<String, Object>>() {}, Feature.OrderedField);
	}
	
	/**
	 * 	json解析为Map对象
	 * 	<br>将解析结果根据key排序
	 * 	
	 * 	@author Pan
	 * 	@param  json	json字符串
	 * 	@return Map
	 */
	public static Map<String, Object> toSortMap(String json) {
		return JSON.parseObject(checkJson(json), new TypeReference<SortedMap<String, Object>>() {});
	}
	
	/**
	 * 	json字符串解析为{@code List<Map<String,Object>>}
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  json	json字符串
	 * 	@return List
	 */
	public static <T> List<Map<String, T>> toListMap(String json) {
		return toBean(json, new TypeReference<List<Map<String, T>>>() {});
	}
	
	/**
	 * 	javaBean转换为json字符串
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  obj		 对象
	 * 	@return String
	 */
	public static <T> String toJson(T obj) {
		return JSON.toJSONString(obj);
	}
	
	/**
	 * 	javaBean转换为json字符串并且分割字符返回StringBuilder
	 * 	<br>List的对象转换成为  多个单个对象的json格式
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param  list 	对象的list
	 * 	@param  split 	自定义分割字符
	 * 	@return	StringBuilder
	 */
	public static <T> StringBuilder toJsonSplit(List<T> list, String split) {
		if (CollUtils.isEmpty(list)) {
			return null;
		}
		
		StringBuilder stringBuilder = new StringBuilder();
		boolean existSplit = ValidParam.required(split);
		int size = list.size();
		
		for (int i = 0; i < size; i++) {
			stringBuilder.append(toJson(list.get(i)));
			stringBuilder.append(split);
			if (i + 1 != size) {
				stringBuilder.append(",");
				if (existSplit) {
					stringBuilder.append("\n");
				}
			}
		}
		return stringBuilder;
	}
	
	/**
	 * 	javaBean转换为json字符串并且特殊字符分割返回StringBuilder 并且增加换行
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param  list 	对象的list
	 * 	@param  split 	自定义分割字符
	 * 	@param  warp 	是否增加换行符
	 * 	@return	StringBuilder
	 */
	public static <T> StringBuilder toJsonSplit(List<T> list, String split, boolean warp) {
		if (CollUtils.isEmpty(list)) {
			return null;
		}
		
		StringBuilder stringBuilder = new StringBuilder();
		boolean existSplit = ValidParam.required(split);
		int size = list.size();
		
		for (int i = 0; i < size; i++) {
			stringBuilder.append(toJson(list.get(i)));
			if (existSplit) {
				stringBuilder.append(split);
			}
			if (i + 1 != size) {
				stringBuilder.append(",");
				if (warp) {
					stringBuilder.append("\n");
				}
			}
		}
		return stringBuilder;
	}
	
	/**
	 * 	List对象转换ListJson的byte数组
	 * 	
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  list	 集合
	 * 	@return byte[]	 byte数组
	 */
	public static <T> byte[] toBytes(List<T> list) {
		if (CollUtils.isEmpty(list)) {
			return new byte[0];
		}
		
		int size = list.size();
		StringBuilder stringBuilder = new StringBuilder();
		
		for (int i = 0; i < size; i++) {
			if (i == 0) {
				stringBuilder.append("[");
			}
			stringBuilder.append(toJson(list.get(i)));
			if (i + 1 == size) {
				stringBuilder.append("]");
			} else {
				stringBuilder.append(",");
				stringBuilder.append("\n");
			}
		}
		return StrEncodeUtils.utf8EncodeToBytes(stringBuilder.toString());
	}
	
	/**
	 * 	List对象转换为 单个对象Json的byte数组
	 * 	含有换行符
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  list	 集合
	 * 	@return byte[] 	 byte数组
	 */
	public static <T> byte[] toSingleBeanBytes(List<T> list) {
		int size = list.size();
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < size; i++) {
			stringBuilder.append(toJson(list.get(i)));
			stringBuilder.append("\n");
		}
		return StrEncodeUtils.utf8EncodeToBytes(stringBuilder.toString());
	}
	
	/**
	 * 	List对象转换为 单个对象Json的byte数组
	 * 	<br>含有换行符
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  list	 集合
	 * 	@return StringBuilder
	 */
	public static <T> StringBuilder toSingleBeanBytesOfBuilder(List<T> list) {
		int size = list.size();
		StringBuilder sbBuffer = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sbBuffer.append(toJson(list.get(i)));
			sbBuffer.append("\n");
		}
		return sbBuffer;
	}
	
	/**
	 * 	List对象转换为 单个对象Json的byte数组 
	 *	<br>并且json值附有逗号(,)和换行符(\n)
	 *
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  list	 集合
	 * 	@return byte[]	 byte数组
	 */
	public static <T> byte[] toSingleBeanSplitBytes(List<T> list) {
		int size = list.size();
		StringBuilder sbBuffer = new StringBuilder();
		
		for (int i = 0; i < size; i++) {
			sbBuffer.append(toJson(list.get(i)));
			if (i + 1 != size) {
				sbBuffer.append(",");
				sbBuffer.append("\n");
			}
		}
		return StrEncodeUtils.utf8EncodeToBytes(sbBuffer);
	}

	/**  
	 *	检测是否为正确的json格式
	 *
	 *	@author Pan
	 *	@param 	str	   字符串
	 *	@return	String
	 */
	public static String checkJson(String str) {
		Assert.isFalse(ValidParam.isEmpty(str), "check json error:传递字符[空]");
		Assert.isFalse(str.length() == 1, 		"check json error:传递字符[非法]");
		
		char c = str.charAt(0);
		char c2 = str.charAt(1);
		//	[
		if (c == '[') {
			return str.substring(str.indexOf(JSON_ARRAY_START_TAG), str.lastIndexOf(JSON_ARRAY_END_TAG) + 1);
		}
		
		//	{[]}
		if (c == '{' && c2 == '[') {
			return str.substring(str.indexOf(JSON_START_TAG), str.lastIndexOf(JSON_END_TAG) + 1);
		}
		
		//	{
		if (c != '{') {
			int indexOf = str.indexOf(JSON_START_TAG);
			int lastIndexOf = str.lastIndexOf(JSON_END_TAG);
			
			if (indexOf != -1 && lastIndexOf != -1) {
				return str.substring(indexOf, lastIndexOf + 1);
			} 
			throw new IllegalArgumentException(StringUtils.format("不合法的JSON数据格式-----传递值:[{}]", str));
		}
		return str;
	}

	/**	
	 * 	验证是否为json格式
	 * 	
	 * 	@author Pan
	 * 	@param 	str  字符串
	 * 	@return	boolean
	 */
	public static boolean hasJson(String str) {
		str = checkJson(str);
		return JSONValidator.from(str).validate();
	}
	
}
